﻿using Grpc.Core;
using log4net;
using log4net.Config;
using System;
using System.Configuration;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using Topshelf;

namespace ConsoleApp_Topshel_Demo
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!  TopShel_Demo");
            var logCfg = new FileInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "log4Net.config"));
            XmlConfigurator.Configure(logCfg);

            //配置和运行宿主服务
            HostFactory.Run(x =>
            {
                //指定服务类型
                x.Service<TCPServerService>(s =>
                {
                    //通过构造函数 去构建一个服务实例
                    s.ConstructUsing(sr => new TCPServerService());
                    //服务启动后动作
                    s.WhenStarted(sr => sr.Start());
                    //服务停止后动作
                    s.WhenStopped(sr => sr.Stop());
                });

                //服务用本地账号来运行
                x.RunAsLocalService();
                //服务描述信息
                x.SetDescription("TCPServer服务");
                //服务显示名称
                x.SetDisplayName(nameof(TCPServerService));
                //服务名称
                x.SetServiceName(nameof(TCPServerService));

            });

        }

        public class TCPServerService
        {
            string _host;
            string _port;
            TcpListener _listener;
            bool loopFlag = false;
            readonly ILog _log = LogManager.GetLogger("RollingLogFileAppender");
            public TCPServerService()
            {
                _host = ConfigurationManager.AppSettings.Get("Host");
                _port = ConfigurationManager.AppSettings.Get("Port");
                _listener = new TcpListener(new IPEndPoint(IPAddress.Parse(_host), int.Parse(_port)));
            }
            public void Start()
            {
                loopFlag = true;
                _listener.Start();
                WriteLog($"TCPServer Listen {_host}:{_port}TCPServer Listen {_host}:{_port}");
                TcpClient tcpClient = null;
                byte[] recBuf = new byte[1024];
                DateTime lastSendHeartTime = DateTime.MinValue;
                Task.Run(() =>
                {
                lab:
                    try
                    {
                        tcpClient = _listener.AcceptTcpClientAsync().Result;
                        var netStream = tcpClient.GetStream();
                        WriteLog($"接收到客户端链接: {tcpClient.Client.RemoteEndPoint}");
                        //tcpClient.GetStream().ReadTimeout = 100;
                        while (loopFlag)
                        {
                            if (netStream.DataAvailable && netStream.CanRead)
                            {
                                int recNu = netStream.Read(recBuf, 0, recBuf.Length);
                                string recStr = Encoding.ASCII.GetString(recBuf, 0, recNu);
                                WriteLog($"{DateTime.Now} recv Client :{recStr}");

                            }
                            if ((DateTime.Now - lastSendHeartTime).TotalSeconds > 5)
                            {
                                netStream.Write(Encoding.ASCII.GetBytes(DateTime.Now.ToString()));
                                lastSendHeartTime = DateTime.Now;
                            }
                            Task.Delay(100).Wait();
                        }
                    }
                    catch (Exception ex)
                    {
                        WriteLog($"{DateTime.Now} 发生异常 ex：{ex.Message}", LogType.Err);
                        Task.Delay(1000).Wait();
                        goto lab;
                    }
                    finally
                    {
                        tcpClient?.Close();
                        tcpClient = null;
                    }

                });
            }
            public void Stop()
            {
                loopFlag = false;
                _listener.Stop();
                _listener = null;
            }

            void WriteLog(string msg, LogType type = LogType.Info)
            {
                switch (type)
                {

                    case LogType.Info:
                        _log.Info(msg);
                        break;
                    case LogType.Debug:
                        _log.Debug(msg);
                        break;
                    case LogType.Err:
                        _log.Error(msg);
                        break;
                    case LogType.War:
                        _log.Warn(msg);
                        break;
                    default:
                        _log.Debug(msg);
                        break;
                }
            }

        }


        enum LogType
        {
            Null,
            Info,
            Debug,
            Err,
            War,
        }

    }
}
